<?php

declare(strict_types=1);

namespace App\CustHub\Service;

use App\CustHub\Amqp\Producers\CommonTaskCenterProducers;
use App\CustHub\Constants\ContactBehaviorTypeConstants;
use App\CustHub\Constants\ContactTaskCenterStatusConstants;
use App\CustHub\Constants\ContactTaskCenterTyperConstants;
use App\CustHub\Dto\CommonProducersDto;
use App\CustHub\Dto\ContactTcContentDto;
use App\CustHub\Event\ContactOperationBehaviorAfter;
use App\CustHub\Event\ContactTaskCenterAfter;
use App\CustHub\Mapper\ChContactTaskCenterMapper;
use App\CustHub\Mapper\ChCorpTagMapper;
use App\CustHub\Mapper\ChSmartTagMapper;
use App\CustHub\Model\ChContact;
use App\CustHub\Model\ChContactTaskCenter;
use Hyperf\Amqp\Producer;
use Hyperf\Coroutine\Coroutine;
use Hyperf\Di\Annotation\Inject;
use Mine\Abstracts\AbstractService;
use Mine\Annotation\Transaction;
use Mine\MineModel;
use function Hyperf\Collection\data_get;
use function Hyperf\Coroutine\co;

/**
 * 客户任务中心服务类
 */
class ChContactTaskCenterService extends AbstractService
{
    public $mapper;

    #[Inject]
    protected ChContactService $contactService;

    public function __construct(ChContactTaskCenterMapper $mapper)
    {
        $this->mapper = $mapper;
    }

    public function list(array $params)
    {
        $type = data_get($params,'type');
        $status = data_get($params,'status');
        $startTime = data_get($params,'start_time');
        $endTime = data_get($params,'end_time');

        $pageSize = $params['page_size'] ?? MineModel::PAGE_SIZE;

        $data = $this->mapper->model::query()
            ->with(['user' => function ($query) {
                $query->select(['id','nickname']);
            }])
            ->where('main_uid',$params['main_uid'])
            ->when(filled($type),function ($query) use ($type){
                $query->where('type',$type);
            })
            ->when(filled($status),function ($query) use ($status){
                $query->where('status',$status);
            })
            ->when(!empty($startTime) && !empty($endTime), function ($query) use ($startTime,$endTime){
                $query->whereBetween('created_at',[$startTime,$endTime]);
            })
            ->orderBy('created_at','desc')
            ->paginate((int)$pageSize);

        $data->getCollection()->transform(function ($item){
            $item->type_text = ContactTaskCenterTyperConstants::getMessage($item->type);
            $item->status_text = ContactTaskCenterStatusConstants::getMessage($item->status);
            return $item;
        });

        return $this->mapper->setPaginate($data);
    }

    public function addTask($uid,$mainUid,$type,ContactTcContentDto $content)
    {
        $contactCount = count($content->getContactIds());
        $tagCount = count($content->getTagIds()) + count($content->getRemoveTagIds());
        $taskData = [
            'uid' => $uid,
            'main_uid' => $mainUid,
            'type' => $type,
            'content' => $content->__toArray(),
            'contact_count' => $contactCount,
            'tag_count' => $tagCount,
        ];
        $taskId =  $this->mapper->save($taskData);
        return container()->get(Producer::class)->produce(new CommonTaskCenterProducers(new CommonProducersDto(
            classname: ChContactTaskCenterService::class,
            method: 'handleTask',
            data: ['task_id' => $taskId]
        )));
    }

    /**
     * 任务终止
     * @param array $params
     * @return bool|int
     */
    public function cancelTask(array $params): bool|int
    {
        return $this->mapper->model::query()
            ->where('id',$params['id'])
            ->where('main_uid',$params['main_uid'])
            ->update([
                'status' => ContactTaskCenterStatusConstants::CANCELED,//任务取消
            ]);
    }

    /**
     * @param array $data
     * @return void
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    #[Transaction]
    public function handleTask(array $data): void
    {
        $taskId = $data['task_id'];

        $taskInfo = ChContactTaskCenter::query()
            ->where('id',$taskId)
            ->first();
        if(empty($taskInfo) || $taskInfo['status'] != ContactTaskCenterStatusConstants::WAITING){
            return;
        }

        //更新任务状态以及开始执行时间
        ChContactTaskCenter::query()
            ->where('id',$taskId)
            ->update([
                'status' => ContactTaskCenterStatusConstants::RUNNING,//任务开始执行
                'begin_time' => time()//任务开始时间
            ]);

        $contactIds = $taskInfo->content['contactIds'];
        $tagIds = $taskInfo->content['tagIds'];
        $removeTagIds = $taskInfo->content['removeTagIds'];
        $extra = $taskInfo->content['extra'];

        $contactList = ChContact::query()
            ->select(['id','user_id','robot_id'])
            ->whereIn('id',$contactIds)
            ->get();

        $finishedContactCount = 0;
        $finishedTagCount = count($tagIds) + count($removeTagIds);
        switch ($taskInfo->type){
            case ContactTaskCenterTyperConstants::PUT_ON_SMART_TAG:
                //打上智能标签
                $addTagContactIds = [];
                foreach ($contactList as $contact){
                    $result = $contact->smartTags()->sync($tagIds,false);
                    !empty($result['attached']) && $addTagContactIds[] = $contact->id;
                    $finishedContactCount++;
                }
                !empty($addTagContactIds) && $this->updateSmartTagContactCnt($addTagContactIds,$tagIds);
                break;
            case ContactTaskCenterTyperConstants::DELETE_SMART_TAG:
                //删除智能标签
                $delTagContactIds = [];
                foreach ($contactList as $contact){
                    $result = $contact->smartTags()->detach($removeTagIds);
                    if($result){
                        $delTagContactIds[] = $contact->id;
                    }
                    $finishedContactCount++;
                }
                !empty($delTagContactIds) && $this->updateSmartTagContactCnt($delTagContactIds,[],$removeTagIds);
                break;
            case ContactTaskCenterTyperConstants::MOVE_SMART_TAG:
                //移动智能标签
                $addTagContactIds = [];
                $delTagContactIds = [];
                foreach ($contactList as $contact){
                    $result = $contact->smartTags()->detach($removeTagIds);
                    $result && $delTagContactIds[] = $contact->id;
                    $result = $contact->smartTags()->sync($tagIds,false);
                    !empty($result['attached']) && $addTagContactIds[] = $contact->id;
                    $finishedContactCount++;
                }
                !empty($addTagContactIds) && $this->updateSmartTagContactCnt($addTagContactIds,$tagIds);
                !empty($delTagContactIds) && $this->updateSmartTagContactCnt($delTagContactIds,[],$removeTagIds);
                break;
            case ContactTaskCenterTyperConstants::PUT_ON_CORP_TAG:
                //打上企业标签
                $finishedContactCount = container()->get(ChContactService::class)->tagMemberOp($contactList,$tagIds);

                break;
            case ContactTaskCenterTyperConstants::DELETE_CORP_TAG:
                //删除企业标签
                $finishedContactCount = container()->get(ChContactService::class)->tagMemberOp($contactList,$removeTagIds,false);

                break;
            case ContactTaskCenterTyperConstants::MOVE_CORP_TAG:
                //移动企业标签
                $finishedContactCount = container()->get(ChContactService::class)->tagMemberOp($contactList,$removeTagIds,false);
                $removeCount = container()->get(ChContactService::class)->tagMemberOp($contactList,$tagIds);
                if($removeCount == 0){
                    $finishedTagCount = $finishedTagCount - count($removeTagIds);
                }
                break;
            case ContactTaskCenterTyperConstants::EDIT_REMARK:
                //修改备注
                $finishedContactCount = count($contactIds);
                foreach ($contactIds as $contactId){
                    co(function () use ($contactId,$extra){
                        $this->contactService->batchEditRemarkHandle($contactId,$extra);
                        Coroutine::sleep(randomFloat(2,5));
                    });
                }
                break;
        }

        ChContactTaskCenter::query()
            ->where('id',$taskId)
            ->update([
                'status' => ContactTaskCenterStatusConstants::FINISHED,//任务完成
                'end_time' => time(),//任务开始时间
                'finished_contact_count' => $finishedContactCount,
                'finished_tag_count' => $finishedContactCount == 0 ? 0 : $finishedTagCount
            ]);

        event(new ContactTaskCenterAfter($taskInfo,$contactList->toArray()));
    }

    /**
     * 更新智能标签客户数量
     * @param array $contactIds
     * @param array $tagIds
     * @param array $removeTagIds
     * @return void
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    public function updateSmartTagContactCnt(array $contactIds,array $tagIds,array $removeTagIds = []): void
    {
        $contactCnt = count($contactIds);
        $smartTagMapper = container()->get(ChSmartTagMapper::class);
        if(!empty($tagIds)){
            $smartTagMapper->updateContactCnt($tagIds,$contactCnt);
            event(new ContactOperationBehaviorAfter($contactIds,ContactBehaviorTypeConstants::CHANGE_TAG,[
                'tagIds' => $tagIds,
                'isAdd' => true,
                'isCorpTags' => false
            ]));
        }

        if(!empty($removeTagIds)){
            $smartTagMapper->updateContactCnt($removeTagIds,-$contactCnt);
            event(new ContactOperationBehaviorAfter($contactIds,ContactBehaviorTypeConstants::CHANGE_TAG,[
                'tagIds' => $removeTagIds,
                'isAdd' => false,
                'isCorpTags' => false
            ]));
        }
    }



}